package cn.maihe.elg.operation.web.ca;

import cn.maihe.elg.operation.centers.epoint.dto.handler.MeiShanApplyGuaranteeResp;
import cn.maihe.elg.operation.centers.epoint.handler.service.MeiShanBaohanApplyService;
import cn.maihe.elg.operation.config.CaDecryptionConfig;
import cn.maihe.elg.operation.model.dto.BaseResponse;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.utils.CaTokenUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

@Api(value = "CA解密", tags = "CA解密")
@RestController
@RequestMapping("/api/caDecryption")
@Slf4j
public class CaDecryptionController {

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;

    @Resource
    private MeiShanBaohanApplyService meiShanBaohanApplyService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private CaDecryptionConfig caDecryptionConfig;

    @ApiOperation(value = "介质CA-获取数字信封", notes = "介质CA-获取数字信封")
    @RequestMapping(value = "/getSercetData", method = RequestMethod.GET)
    public BaseResponse<Object> getSercetData(@RequestParam String ordersn) {
        log.info("getSercetData ordersn:{}",ordersn);
        String acceptOrderNo = meiShanBaohanApplyService.getAcceptOrderNoPlaintext(ordersn);
        log.info("getSercetData acceptOrderNo:{}",acceptOrderNo);
        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);

        if (Objects.isNull(acceptOrderInfoDO)) {
            log.error("getSercetData acceptOrderInfo is null. acceptOrderNo={}", acceptOrderNo);
            return  BaseResponse.error("查询不到订单数据");
        }

        JSONObject ciphertext  =JSON.parseObject(acceptOrderInfoDO.getCiphertext());
        if(Objects.isNull(ciphertext) || Objects.isNull(ciphertext.get("digitalenvelope"))) {
            log.error("getSercetData digitalenvelope is null. acceptOrderNo={}", acceptOrderNo);
            return  BaseResponse.error("查询不到数字信封");
        }

        HashMap<String, Object> data = new HashMap<>();
        data.put("digitalenvelope",ciphertext.get("digitalenvelope"));
        return BaseResponse.success(data);
    }

    @ApiOperation(value = "介质CA-更新数字信封（明文）", notes = "介质CA-更新数字信封（明文）")
    @RequestMapping(value = "/updateDigitalenvelope", method = RequestMethod.PUT)
    public BaseResponse<Object> updateDigitalenvelope(@RequestParam String digitalenvelope, @RequestParam String ordersn) {
        log.info("updateDigitalenvelope digitalenvelope:{},ordersn:{}",digitalenvelope,ordersn);
        if (ordersn != null && digitalenvelope != null) {
            MeiShanApplyGuaranteeResp meiShanApplyGuaranteeResp = meiShanBaohanApplyService.baohanApply(ordersn, digitalenvelope,"3");

            HashMap<Object, Object> data = new HashMap<>();
            data.put("payurl",meiShanApplyGuaranteeResp.getData().getRedirecturl());
            return BaseResponse.success(data);
        } else {
            return BaseResponse.error("数字信封或受理订单号为空");
        }

    }

    @ApiOperation(value = "生成二维码接口", notes = "生成二维码接口")
    @RequestMapping(value = "/createQR", method = RequestMethod.GET)
    @ResponseBody
    public BaseResponse<Object> createQR(@RequestParam String ordersn,@RequestParam String decryptionType) {
        log.info("createQR ordersn:{};decryptionType:{}",ordersn,decryptionType);
        //decryptionType 解密类型 1：标正通 ,2:全国CA互认
        if(!"1".equals(decryptionType) && !"2".equals(decryptionType) ){
            log.error("非法的解密类型 decryptionType={}", decryptionType);
            return BaseResponse.error("非法的解密类型");
        }

        String acceptOrderNo = meiShanBaohanApplyService.getAcceptOrderNoPlaintext(ordersn);
        log.info("createQR acceptOrderNo:{}", acceptOrderNo);

        AcceptOrderInfoDO acceptOrderInfoDO = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);
        if (acceptOrderInfoDO == null) {
            log.error("createQR acceptOrderNo={}", acceptOrderNo, "查询不到订单数据");
            return BaseResponse.error("查询不到订单数据");
        }

        JSONObject getCiphertext = JSON.parseObject(acceptOrderInfoDO.getCiphertext());
        String encrypt;
        if("1".equals(decryptionType)){
            encrypt = getCiphertext.getString("digitalenvelope");
        }else {
            encrypt = JSON.parseObject(getCiphertext.getString("digitalenvelope")).getString("encryptStr");
        }

        String url;
        if("1".equals(decryptionType)){
            url = caDecryptionConfig.getBaseUrl() + caDecryptionConfig.getBztCreateQrUrl();
        }else {
            url = caDecryptionConfig.getBaseUrl() + caDecryptionConfig.getNationalCaCreateQrUrl();
        }

        JSONObject reqobj = new JSONObject();
        JSONObject head = new JSONObject();
        head.put("platformcode", getPlatformCode());
        head.put("timestamp", getDateTime());
        head.put("token", createToken());
        JSONObject params = new JSONObject();

        JSONObject qrinfo = new JSONObject();
        qrinfo.put("platformcode", getPlatformCode());
        qrinfo.put("qrcodetype", 5);
        qrinfo.put("timestamp", getDateTime());

        JSONObject certobject = new JSONObject();
        certobject.put("devicenum", "");
        certobject.put("signcert", "");
        certobject.put("dognum", "");
        certobject.put("decryptcert", "");
        qrinfo.put("certobject", certobject);

        if("2".equals(decryptionType)){
            JSONObject ext = new JSONObject();
            ext.put("qrapptype","391");
            qrinfo.put("ext", ext);
        }

        JSONObject decryptobjects = new JSONObject();
        decryptobjects.put("encryed", encrypt);
        decryptobjects.put("org", "");
        decryptobjects.put("oid", "");
        decryptobjects.put("desc", "");
        decryptobjects.put("result", "");

        //将decryptobjects signatureobjects内数据转为数组
        List<JSONObject> listDecryptobjects = Arrays.asList(JSON.parseObject(String.valueOf(decryptobjects)));
        JSONObject signatureobjects = new JSONObject();
        List<JSONObject> listSignatureobjects = Arrays.asList(JSON.parseObject(String.valueOf(signatureobjects)));

        qrinfo.put("decryptobjects", listDecryptobjects);
        qrinfo.put("signatureobjects", listSignatureobjects);
        params.put("qrinfo", qrinfo);
        reqobj.put("head", head);
        reqobj.put("params", params);
        String content = "";
        String qrcodeid = "";

        try {
            log.info("createQR url:{},reqobj:{}",url,reqobj.toJSONString());
            //正式数据
            String rtn = String.valueOf( restTemplate.postForEntity(url, reqobj, String.class).getBody());
            log.info("createQR rtn:{}",rtn);

            JSONObject jobj = JSON.parseObject(rtn);
            JSONObject custom = jobj.getJSONObject("custom");
            if("1".equals(decryptionType)){
                content = custom.getString("content");
            }else {
                content = custom.getString("qrimagebase64");
            }
            qrcodeid = custom.getString("qrcodeid");

            HashMap<String, Object> data = new HashMap<>();
            data.put("qrcodeid", qrcodeid);
            data.put("content", content);
            return BaseResponse.success(data);
        } catch (Exception e) {
            log.error("createQR error:{}",e.getMessage(),e);
            return BaseResponse.error("createQR error");
        }
    }

    @ApiOperation(value = "获取二维码结果", notes = "获取二维码结果")
    @RequestMapping(value = "/queryResultQR", method = RequestMethod.GET)
    public BaseResponse<Object> queryResult(@RequestParam String qrcodeid, @RequestParam String ordersn,@RequestParam String decryptionType) {
        log.info("queryResultQR qrcodeid:{};ordersn:{};decryptionType:{}",qrcodeid,ordersn,decryptionType);
        String acceptOrderNo = meiShanBaohanApplyService.getAcceptOrderNoPlaintext(ordersn);
        log.info("queryResultQR acceptOrderNo:{}", acceptOrderNo);

        //decryptionType 解密类型 1：标正通 ,2:全国CA互认
        if(!"1".equals(decryptionType) && !"2".equals(decryptionType) ){
            log.error("非法的解密类型 decryptionType={}", decryptionType);
            return BaseResponse.error("非法的解密类型");
        }

        String url;
        if("1".equals(decryptionType)){
            url = caDecryptionConfig.getBaseUrl() + caDecryptionConfig.getBztQueryResultQrUrl();
        }else {
            url = caDecryptionConfig.getBaseUrl() + caDecryptionConfig.getNationalCaQueryResultQrUrl();
        }

        JSONObject reqobj = new JSONObject();
        JSONObject head = new JSONObject();
        head.put("platformcode", getPlatformCode());
        head.put("timestamp", getDateTime());
        head.put("token", createToken());
        JSONObject params = new JSONObject();
        params.put("qrcodeid", qrcodeid);
        reqobj.put("head", head);
        reqobj.put("params", params);

        try {

            log.info("queryResultQR url:{},reqobj:{}",url,reqobj.toJSONString());
            String rtn = String.valueOf( restTemplate.postForEntity(url, reqobj, String.class).getBody());
            log.info("queryResultQR rtn:{}",rtn);

            JSONObject rtnobj = JSON.parseObject(rtn);
            // 扫码状态
            String qrstatus = rtnobj.getJSONObject("custom").getString("qrstatus");

            if (!Objects.equals(qrstatus, "02")){
                log.error("queryResultQR qrstatus:{}",qrstatus);
                return BaseResponse.error("未确认扫码");
            }

            // 获取qrinfo节点
            JSONObject qrinfoNode = rtnobj.getJSONObject("custom").getJSONObject("qrinfo");

            String digitalenvelope="";
            ObjectMapper mapper = new ObjectMapper();
            JsonNode decryptobjectsNode = mapper.readTree(String.valueOf(qrinfoNode));
            // 检查decryptobjects数组是否存在且获取解密数据
            if (decryptobjectsNode.has("decryptobjects") && !decryptobjectsNode.get("decryptobjects").isNull()) {
                JsonNode decryptObjects = decryptobjectsNode.get("decryptobjects");
                if (decryptObjects.isArray() && decryptObjects.size() > 0) {
                    JsonNode firstObject = decryptObjects.get(0);
                    if (firstObject.has("org")) {
                        digitalenvelope=firstObject.get("org").asText();
                    }
                }

                if(StringUtils.isEmpty(digitalenvelope)){
                    log.error("queryResultQR digitalenvelope isEmpty");
                    return BaseResponse.error("digitalenvelope isEmpty");
                }

                HashMap<Object, Object> data = new HashMap<>();
                MeiShanApplyGuaranteeResp meiShanApplyGuaranteeResp = meiShanBaohanApplyService.baohanApply(ordersn, digitalenvelope,decryptionType);
                data.put("payurl",meiShanApplyGuaranteeResp.getData().getRedirecturl());
                return BaseResponse.success(data);
            }else{
                log.error("queryResultQR decryptobjects is null");
                return BaseResponse.error("decryptobjects is null");
            }

        } catch (Exception e) {
            log.error("queryResultQR error:{}",e.getMessage(),e);
            return BaseResponse.error("queryResultQR error");
        }
    }

    private String createToken() {
        return CaTokenUtil.createToken(caDecryptionConfig.getTokenKey(), caDecryptionConfig.getTokenSecret());
    }

    private String getPlatformCode() {
        return caDecryptionConfig.getPlatformCode();
    }

    private String getDateTime() {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    }

}
